/* -------------------------------------------------------------------------- *
   TestWinUnit - Maria Blees (maria.blees@microsoft.com)

   File: MacroAssertTest.cpp

   This file contains tests for the ASSERT* macros (also exercising Assert class).
   Exceptions are expected to be thrown by the ASSERT* macros and are caught
   as part of the tests.
 * -------------------------------------------------------------------------- */
#include "WinUnit.h"

BEGIN_TEST(MacroAssertFail)
{
    bool exceptionThrown = false;
    try
    {
        WIN_ASSERT_FAIL(_T("This is the reason for failure."));
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate that WIN_ASSERT_FAIL failed.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertFailWithVarParams)
{
    bool exceptionThrown = false;
    try
    {
        WIN_ASSERT_FAIL(_T("Formatting example: %s %d, %d."), _T("October"), 13, 1975);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_FAIL failed, followed by a formatting example.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertTrue)
{
    bool exceptionThrown = false;
    try
    {
        WIN_ASSERT_TRUE((3 > 4));
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_TRUE failed.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertTrueWithMessage)
{
    bool exceptionThrown = false;
    try
    {
        WIN_ASSERT_TRUE((3 > 4), _T("Formatting example: %s %d, %d."), _T("October"), 13, 1975);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_TRUE failed, with formatting example.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertTrueSucceeds)
{
    WIN_ASSERT_TRUE(4 > 3);
}
END_TEST

BEGIN_TEST(MacroAssertFalse)
{
    bool exceptionThrown = false;
    try
    {
        WIN_ASSERT_FALSE(4 > 3);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE(L"INFO: Next line should indicate WIN_ASSERT_FALSE failed.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertFalseWithMessage)
{
    bool exceptionThrown = false;
    try
    {
        WIN_ASSERT_FALSE((4 > 3), _T("Formatting example: %s %d, %d."), _T("October"), 13, 1975);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_FALSE failed, with formatting example.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertFalseSucceeds)
{
    WIN_ASSERT_FALSE(3 == 4);
}
END_TEST

BEGIN_TEST(MacroAssertEqual)
{
    bool exceptionThrown = false;
    try
    {
        WIN_ASSERT_EQUAL(5, 6);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_EQUAL failed.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertEqualWithDifferentSizesButSameValue)
{
    unsigned short s = 0x0000;
    unsigned int i = 0x00000000;
    WIN_ASSERT_NOT_EQUAL(sizeof(s), sizeof(i));

    WIN_ASSERT_EQUAL(s, i);
    WIN_ASSERT_EQUAL(i, s);
}
END_TEST

BEGIN_TEST(MacroAssertEqualWithDifferentSizesAndDifferentValue)
{
    unsigned short s = 0x0000;
    unsigned int i = 0x10000000;

    WIN_ASSERT_NOT_EQUAL(sizeof(s), sizeof(i));

    {
        bool exceptionThrown = false;
        try
        {
            WIN_ASSERT_EQUAL(s, i);
        }
        catch(WinUnit::AssertException& e)
        {
            exceptionThrown = true;
            WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_EQUAL failed.\n");
            WIN_TRACE(L"OUTPUT: %s\n", e.Message());
        }
        WIN_ASSERT_TRUE(exceptionThrown);
    }

    {
        bool exceptionThrown = false;
        try
        {
            WIN_ASSERT_EQUAL(i, s);
        }
        catch(WinUnit::AssertException& e)
        {
            exceptionThrown = true;
            WIN_TRACE(L"INFO: Next line should indicate WIN_ASSERT_EQUAL failed.\n");
            WIN_TRACE(L"OUTPUT: %s\n", e.Message());
        }
        WIN_ASSERT_TRUE(exceptionThrown);
    }
}
END_TEST

BEGIN_TEST(MacroAssertEqualWithMessage)
{
    bool exceptionThrown = false;
    try
    {
        WIN_ASSERT_EQUAL(5, 6, _T("Formatting example: %s %d, %d."), _T("October"), 13, 1975);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_EQUAL failed, with formatting example.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertEqualWithStrings)
{
    bool exceptionThrown = false;
    try
    {
        WIN_ASSERT_EQUAL((void*)"hello", (void*)"world");
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_EQUAL failed.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertEqualWithNumbers)
{
    bool exceptionThrown = false;
    try
    {
        WIN_ASSERT_EQUAL(3, 4);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_EQUAL failed.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

struct Foo 
{
    int _n;
    Foo(int n) : _n(n) {}
//    bool operator==(const Foo& rhs) { return _n == rhs._n; }
    friend bool operator==(const Foo& lhs, const Foo& rhs) 
    { 
        return lhs._n == rhs._n; 
    }
};


BEGIN_TEST(MacroAssertEqualWithObject)
{
    Foo f1(1);
    Foo f2(2);
    bool exceptionThrown = false;
    try
    {
        WIN_ASSERT_EQUAL(f1, f2);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_EQUAL failed.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertEqualSucceeds)
{
    WIN_ASSERT_EQUAL(3, 3);
}
END_TEST

BEGIN_TEST(MacroAssertNotEqual)
{
    bool exceptionThrown = false;
    try
    {
        WIN_ASSERT_NOT_EQUAL(6, 6);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_NOT_EQUAL failed.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertNotEqualWithMessage)
{
    bool exceptionThrown = false;
    try
    {
        WIN_ASSERT_NOT_EQUAL(6, 6, _T("Formatting example: %s %d, %d."), _T("October"), 13, 1975);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate that WIN_ASSERT_NOT_EQUAL failed, with formatting example.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertNotEqualSucceeds)
{
    WIN_ASSERT_NOT_EQUAL(6, 7);
}
END_TEST

BEGIN_TEST(MacroAssertStringEqualWideChar)
{
    wchar_t* string1 = L"Hello";
    wchar_t* string2 = L"World";
    bool exceptionThrown = false;
    try
    {
        WIN_ASSERT_STRING_EQUAL(string1, string2);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_STRING_EQUAL failed.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertStringEqualWideCharWithMessage)
{
    wchar_t* string1 = L"Hello";
    wchar_t* string2 = L"World";
    bool exceptionThrown = false;
    try
    {
        WIN_ASSERT_STRING_EQUAL(string1, string2, _T("Formatting example: %s %d, %d."), _T("October"), 13, 1975);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_STRING_EQUAL failed, with formatting example.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertStringEqualWideCharSucceeds)
{
    wchar_t* string1 = L"Hello";
    wchar_t* string2 = L"Hello";
    WIN_ASSERT_STRING_EQUAL(string1, string2);
}
END_TEST

BEGIN_TEST(MacroAssertStringEqualAnsi)
{
    char* string1 = "Hello";
    char* string2 = "World";
    bool exceptionThrown = false;
    try
    {
        WIN_ASSERT_STRING_EQUAL(string1, string2);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE(L"INFO: Next line should indicate WIN_ASSERT_STRING_EQUAL failed.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertStringEqualAnsiWithMessage)
{
    char* string1 = "Hello";
    char* string2 = "World";
    bool exceptionThrown = false;
    try
    {
        WIN_ASSERT_STRING_EQUAL(string1, string2, _T("Formatting example: %s %d, %d."), _T("October"), 13, 1975);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_STRING_EQUAL failed, with formatting example.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertStringEqualAnsiSucceeds)
{
    char* string1 = "Hello";
    char* string2 = "Hello";
    WIN_ASSERT_STRING_EQUAL(string1, string2);
}
END_TEST

BEGIN_TEST(MacroAssertZero)
{
    bool exceptionThrown = false;
    try
    {
        int n = 5;
        WIN_ASSERT_ZERO(n);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_ZERO failed.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertZeroWithMessage)
{
    bool exceptionThrown = false;
    try
    {
        int n = 5;
        WIN_ASSERT_ZERO(n, _T("Formatting example: %s %d, %d."), _T("October"), 13, 1975);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_ZERO failed, with formatting example.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertZeroSucceeds)
{
    int n = 5 - 5;
    WIN_ASSERT_ZERO(n);
}
END_TEST

BEGIN_TEST(MacroAssertNotZero)
{
    bool exceptionThrown = false;
    try
    {
        int n = 0;
        WIN_ASSERT_NOT_ZERO(n);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_NOT_ZERO failed.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertNotZeroWithMessage)
{
    bool exceptionThrown = false;
    try
    {
        int n = 0;
        WIN_ASSERT_NOT_ZERO(n, _T("Formatting example: %s %d, %d."), _T("October"), 13, 1975);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_NOT_ZERO failed, with formatting example.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertNotZeroSucceeds)
{
    int n = 5 - 4;
    WIN_ASSERT_NOT_ZERO(n);
}
END_TEST

BEGIN_TEST(MacroAssertNull)
{
    bool exceptionThrown = false;
    try
    {
        TCHAR* foo = _T("hello");
        WIN_ASSERT_NULL(foo);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_NULL failed.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertNullWithMessage)
{
    bool exceptionThrown = false;
    try
    {
        TCHAR* foo = _T("hello");
        WIN_ASSERT_NULL(foo, _T("Formatting example: %s %d, %d."), _T("October"), 13, 1975);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_NULL failed, with formatting example.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertNullSucceeds)
{
    int* p = NULL;
    WIN_ASSERT_NULL(p);
}
END_TEST

BEGIN_TEST(MacroAssertNotNull)
{
    bool exceptionThrown = false;
    try
    {
        TCHAR* foo = NULL;
        WIN_ASSERT_NOT_NULL(foo);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_NOT_NULL failed.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertNotNullWithMessage)
{
    bool exceptionThrown = false;
    try
    {
        TCHAR* foo = NULL;
        WIN_ASSERT_NOT_NULL(foo, _T("Formatting example: %s %d, %d."), _T("October"), 13, 1975);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_NOT_NULL failed, with formatting example.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertNotNullSucceeds)
{
    int n = 5;
    WIN_ASSERT_NOT_NULL(&n);
}
END_TEST

BEGIN_TEST(MacroAssertWinapiTrueNoMessage)
{
    bool exceptionThrown = false;
    try
    {
        WIN_ASSERT_WINAPI_SUCCESS(0 != ::DeleteFile(_T("Foo")));
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_WINAPI_SUCCESS failed.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertWinapiTrueWithMessage)
{
    bool exceptionThrown = false;
    try
    {
        WIN_ASSERT_WINAPI_SUCCESS(0 != ::DeleteFile(_T("Foo")), _T("Formatting example: %s %d, %d."), _T("October"), 13, 1975);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_WINAPI_SUCCESS failed, with formatting example.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST

BEGIN_TEST(MacroAssertWinapiTrueSucceeds)
{
    WIN_ASSERT_WINAPI_SUCCESS(5 == 5);
}
END_TEST

namespace
{
    class MyException
    {
    };

    void ThrowMyException()
    {
        throw MyException();
    }

    void NoThrow() throw(...)
    {
    }
}

#pragma warning(push)
#pragma warning(disable:4702)
BEGIN_TEST(MacroAssertThrows)
{
    bool exceptionThrown = false;
    try
    {
//        WIN_ASSERT_THROWS(ThrowMyException(), MyException);
        WIN_ASSERT_THROWS(NoThrow(), MyException);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_THROWS failed.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST
#pragma warning(pop)

#pragma warning(push)
#pragma warning(disable:4702)
BEGIN_TEST(MacroAssertThrowsWithMessage)
{
    bool exceptionThrown = false;
    try
    {
//        WIN_ASSERT_THROWS(ThrowMyException(), MyException);
        WIN_ASSERT_THROWS(NoThrow(), MyException, _T("Formatting example: %s %d, %d."), _T("October"), 13, 1975);
    }
    catch(WinUnit::AssertException& e)
    {
        exceptionThrown = true;
        WIN_TRACE("INFO: Next line should indicate WIN_ASSERT_THROWS failed, with formatting example.\n");
        WIN_TRACE(L"OUTPUT: %s\n", e.Message());
    }
    WIN_ASSERT_TRUE(exceptionThrown);
}
END_TEST
#pragma warning(pop)

BEGIN_TEST(MacroAssertThrowsSucceeds)
{
    WIN_ASSERT_THROWS(ThrowMyException(), MyException);
}
END_TEST

#if 0

// Here I was testing cases where fixture throws on setup/teardown.  This
// was only enabled temporarily because I don't want to have failing tests.

// ---------------------------------------------------------------------

FIXTURE(FixtureWhereSetupThrows);

SETUP(FixtureWhereSetupThrows)
{
    WIN_ASSERT_FAIL(_T("FixtureWhereSetupThrows-- Setup throws!"));
}

TEARDOWN(FixtureWhereSetupThrows)
{
}

// ----------------------------------------------------------------------

FIXTURE(FixtureWhereTeardownThrows);

SETUP(FixtureWhereTeardownThrows)
{
}

TEARDOWN(FixtureWhereTeardownThrows)
{
    WIN_ASSERT_FAIL(_T("FixtureWhereTeardownThrows-- Teardown throws!"));
}

// ----------------------------------------------------------------------

FIXTURE(FixtureWhereSetupAndTeardownThrow);

SETUP(FixtureWhereSetupAndTeardownThrow)
{
    WIN_ASSERT_FAIL(_T("FixtureWhereSetupAndTeardownThrow-- Setup throws!"));
}

TEARDOWN(FixtureWhereSetupAndTeardownThrow)
{
    WIN_ASSERT_FAIL(_T("FixtureWhereSetupAndTeardownThrow-- Teardown throws!"));
}

// ----------------------------------------------------------------------


// Test case in which setup throws
BEGIN_TESTF(TestFixtureSetupThrows, FixtureWhereSetupThrows)
{
    WIN_ASSERT_TRUE(5 == 5, _T("Just asserting a fact"));
}
END_TESTF

// Test case in which teardown throws
BEGIN_TESTF(TestFixtureTeardownThrows, FixtureWhereTeardownThrows)
{
    WIN_ASSERT_TRUE(5 == 5, _T("Just asserting a fact"));
}
END_TESTF

// Test case in which setup throws and there is another assert
BEGIN_TESTF(TestFixtureSetupThrowsAndAnotherAssert, FixtureWhereSetupThrows)
{
    WIN_ASSERT_FAIL(_T("Test fails"));
}
END_TESTF

// Test case in which teardown throws and there is another assert
BEGIN_TESTF(TestFixtureTeardownThrowsAndAnotherAssert, FixtureWhereTeardownThrows)
{
    WIN_ASSERT_FAIL(_T("Test fails"));
}
END_TESTF

// Test case in which both setup and teardown throw
BEGIN_TESTF(TestFixtureSetupAndTeardownThrow, FixtureWhereSetupAndTeardownThrow)
{
    WIN_ASSERT_TRUE(5 == 5, _T("Just asserting a fact"));
}
END_TESTF


#endif 

